package others;

import org.apache.http.HttpHost;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class ApacheHttpClientExample {
    public static CloseableHttpClient createCustomHttpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        // 连接池配置
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(200);          // 最大连接数
        connManager.setDefaultMaxPerRoute(50); // 每个路由（目标主机）的最大并发连接数
        connManager.closeIdleConnections(60, TimeUnit.SECONDS); // 关闭空闲超时连接

        // 超时配置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000)    // 连接建立超时（5秒）
                .setSocketTimeout(15000)    // 数据传输超时（15秒）
                .setConnectionRequestTimeout(3000) // 从连接池获取连接的超时（3秒）
                .build();

        // 创建一个信任所有证书的TrustManager
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }
                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }
                }};

        // SSL配置（信任自签名证书）
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);


        // 重试策略
        StandardHttpRequestRetryHandler retryHandler = new StandardHttpRequestRetryHandler(
                3,      // 最大重试次数
                true    // 对非幂等请求（如POST）也重试（需业务确保安全性）
        );

        // 构建HttpClient
        return HttpClientBuilder.create()
                .setConnectionManager(connManager)          // 连接池
                .setDefaultRequestConfig(requestConfig)     // 超时配置
                .setSSLSocketFactory(sslsf)      // SSL配置
                .setRetryHandler(retryHandler)              // 重试策略
//                .setProxy(new HttpHost("proxy.example.com", 8080)) // 代理服务器
                .disableCookieManagement()                  // 禁用Cookie管理（按需启用）
//                .setUserAgent("Custom-Client/1.0")          // 自定义User-Agent
                .addInterceptorFirst((HttpRequestInterceptor) (request, context) ->
                        request.addHeader("X-Request-ID", UUID.randomUUID().toString())) // 自定义请求头
                .build();
    }

    public static void main(String[] args) {
        try {
            CloseableHttpClient httpClient = createCustomHttpClient();
            // 使用httpClient进行HTTP请求
            // ...
            CloseableHttpResponse execute = httpClient.execute(new HttpGet("https://www.ccgp.gov.cn/cggg/dfgg/gkzb/202312/t20231208_21232813.htm"));
            InputStream content = execute.getEntity().getContent();
            System.out.println(new String(content.readAllBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}